#pragma once

#include "base/mutex.h"
#include "fiber.h"
#include "thread.h"
#include <atomic>
#include <cstddef>
#include <functional>
#include <list>
#include <memory>
#include <vector>
namespace Yizhi{
    class Scheduler{
        public:
        typedef std::function<void()> CallBackType;
        typedef std::shared_ptr<Scheduler> ptr;
        typedef Mutex MutexType;


        public:
        Scheduler(size_t threads=1,const std::string &name="",bool user_caller=true);

        const std::string& GetName();

        ///@brief 调度开始
        void start();

        ///@brief 调度结束
        void stop();


       

        bool hasIdleThreads(){
            return m_idleThreadcount==0;
        }

        ///@brief 虚析构函数
        virtual ~Scheduler();

        void SetThis();
        static Scheduler* GetThis();
        static Fiber* GetMainFiber();

    

        protected:
         ///@brief 调度入口 
        void run();


        virtual void tickle();
        virtual void idle();
        virtual bool isStoped();


        public:
        template<class FiberOrCb>
        void scheduler(FiberOrCb f,int thread=-1){
            bool need_tick=false;
            {
                MutexType::Lock lock(m_mutex);
                need_tick=schedulerNoLock(f,thread);
            }
            if(need_tick){
                tickle();
            }
        }

        template<class InputIterator>
        void scheduler(InputIterator begin,InputIterator end){
            bool need_tick=false;
            {  MutexType::Lock lock(m_mutex);
               while(begin!=end){
                need_tick=schedulerNoLock(&*begin)||need_tick;
                ++begin;
                }
            }
            if(need_tick){
                tickle();
            }
        }

        private:
        template<class FiberOrCb>
        bool schedulerNoLock(FiberOrCb f,int thread=-1){
            bool need_tick=m_taskpools.empty();
            Task t(f,thread);
            if(t.m_cb||t.m_fiber){
                m_taskpools.push_back(t);
            }
            return need_tick;
        }

        private:
        struct Task{
            Task(CallBackType cb,int thread=-1)
            :m_cb(cb)
            ,m_threads(thread){
                m_fiber=nullptr;
            }

            Task(Fiber::ptr f,int thread=-1)
            :m_fiber(f)
            ,m_threads(thread){
                m_cb=nullptr;
            }

            Task(CallBackType* cb,int thread=-1)
            :m_threads(-1){
                m_cb.swap(*cb);
                m_fiber=nullptr;
            }
            Task(Fiber::ptr *f,int thread=-1)
            :m_threads(thread){
                m_fiber.swap(*f);
                m_cb=nullptr;
            }

            Task(int thread=-1){
                thread=-1;
            }

            void reset(){
                m_cb=nullptr;
                m_fiber=nullptr;
                m_threads=-1;
            }

            ///@brief 变量区
            Fiber::ptr m_fiber;
            CallBackType m_cb;
            int m_threads;
            
        };


        private:
        MutexType m_mutex;
        std::vector<Thread::ptr> m_threads;
        std::list<Task>m_taskpools;
        std::string m_name;

        protected:
        size_t m_threadCount=0;
        Fiber::ptr m_rootFiber;
        bool m_stopping=true;
        bool m_autostop=false;
        std::vector<int> m_threadIds;
        std::atomic<size_t> m_idleThreadcount={0};
        std::atomic<size_t> m_activeThreadCount={0};
        int m_rootThread=0;
        
    };
}